package rad.framework.uml2.classdiagram.part;

import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import rad.framework.uml2.classdiagram.edit.parts.PackageEditPart;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.OperationHistoryFactory;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.core.services.ViewService;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.emf.core.GMFEditingDomainFactory;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.dialogs.WizardNewFileCreationPage;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.navigator.CommonActionProvider;
import org.eclipse.ui.navigator.ICommonActionExtensionSite;
import org.eclipse.ui.navigator.ICommonMenuConstants;
import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite;
import org.eclipse.uml2.uml.Package;

/**
 * @generated
 */
public class UMLInitDiagramAction extends CommonActionProvider implements
		IMenuListener, IInputValidator {

	/**
	 * @generated
	 */
	public String isValid(String newText) {
		IStatus status = ResourcesPlugin.getWorkspace().validateName(newText,
				IResource.FILE);
		if (!status.isOK()) {
			return status.getMessage();
		}
		return null;
	}

	/**
	 * @generated
	 */
	private class NewDiagramFileWizard extends Wizard {

		/**
		 * @generated
		 */
		private TransactionalEditingDomain myEditingDomain = GMFEditingDomainFactory.INSTANCE
				.createEditingDomain();

		/**
		 * @generated
		 */
		private WizardNewFileCreationPage myFileCreationPage;

		private static final String FILE_EXT = "uml_diagram";

		/**
		 * @generated
		 */
		public void addPages() {
			String name = getSelection().getQualifiedName() + "." + FILE_EXT;
			name = name.replaceAll("::", "-");
			myFileCreationPage = new WizardNewFileCreationPage(
					"Initialize new Ecore diagram file",
					(IStructuredSelection) getContext().getSelection());
			myFileCreationPage.setFileName(name);
			myFileCreationPage.setTitle("Diagram file");
			myFileCreationPage
					.setDescription("Create new diagram and initialize it using specified UML model content");
			addPage(myFileCreationPage);
		}

		/**
		 * @generated
		 */
		public boolean performFinish() {
			final EObject diagramModelObject = getSelection();
			if (diagramModelObject == null) {
				MessageDialog.openError(getShell(), "Error",
						"Failed to load user model");
				return false;
			}

			IFile diagramFile = myFileCreationPage.createNewFile();
			ResourceSet resourceSet = myEditingDomain.getResourceSet();
			final Resource diagramResource = resourceSet.createResource(URI
					.createPlatformResourceURI(diagramFile.getFullPath()
							.toString()));

			List affectedFiles = new LinkedList();
			affectedFiles.add(diagramFile);

			AbstractTransactionalCommand command = new AbstractTransactionalCommand(
					myEditingDomain,
					"Initializing diagram contents", affectedFiles) { //$NON-NLS-1$
				protected CommandResult doExecuteWithResult(
						IProgressMonitor monitor, IAdaptable info)
						throws ExecutionException {
					int diagramVID = UMLVisualIDRegistry
							.getDiagramVisualID(diagramModelObject);
					if (diagramVID != PackageEditPart.VISUAL_ID) {
						return CommandResult
								.newErrorCommandResult("Incorrect model object stored as a root resource object"); //$NON-NLS-1$
					}
					Diagram diagram = ViewService.createDiagram(
							diagramModelObject, PackageEditPart.MODEL_ID,
							UMLDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT);
					diagramResource.getContents().add(diagram);
					return CommandResult.newOKCommandResult();
				}
			};

			try {
				OperationHistoryFactory.getOperationHistory().execute(command,
						new NullProgressMonitor(), null);
				diagramResource.save(Collections.EMPTY_MAP);
				IDE.openEditor(((ICommonViewerWorkbenchSite) aConfig
						.getViewSite()).getPage(), diagramFile);
			} catch (ExecutionException e) {
				UMLDiagramEditorPlugin.getInstance().logError(
						"Unable to create model and diagram", e); //$NON-NLS-1$
			} catch (IOException ex) {
				UMLDiagramEditorPlugin
						.getInstance()
						.logError(
								"Save operation failed for: " + diagramFile.getFullPath().toString(), ex); //$NON-NLS-1$
			} catch (PartInitException ex) {
				UMLDiagramEditorPlugin.getInstance().logError(
						"Unable to open editor", ex); //$NON-NLS-1$
			}
			return true;
		}
	}

	public void menuAboutToShow(IMenuManager manager) {
		// TODO Auto-generated method stub

	}

	public void fillContextMenu(IMenuManager aMenu) {
		aMenu.appendToGroup(ICommonMenuConstants.GROUP_NEW, new InitAction(
				"New Class Diagram", getContext().getSelection()));
	}

	public class InitAction extends Action {

		IStructuredSelection selection;

		public InitAction(String name, ISelection selection) {
			this.selection = (IStructuredSelection) selection;
			setText(name);
			setToolTipText(name + " Tip");
			setDescription(name + " Description");
		}

		public void run() {
			NewDiagramFileWizard wizard = new NewDiagramFileWizard();
			IDialogSettings pluginDialogSettings = UMLDiagramEditorPlugin
					.getInstance().getDialogSettings();
			IDialogSettings initDiagramFileSettings = pluginDialogSettings
					.getSection("InisDiagramFile"); //$NON-NLS-1$
			if (initDiagramFileSettings == null) {
				initDiagramFileSettings = pluginDialogSettings
						.addNewSection("InisDiagramFile"); //$NON-NLS-1$
			}
			wizard.setDialogSettings(initDiagramFileSettings);
			wizard.setForcePreviousAndNextButtons(false);
			wizard.setWindowTitle("Initialize new Class diagram file");

			WizardDialog dialog = new WizardDialog(aConfig.getViewSite()
					.getShell(), wizard);
			dialog.create();
			dialog.getShell().setSize(
					Math.max(500, dialog.getShell().getSize().x), 500);
			dialog.open();
		}
	}

	private ICommonActionExtensionSite aConfig;

	@Override
	public void init(ICommonActionExtensionSite aConfig) {
		this.aConfig = aConfig;
	}

	public Package getSelection() {
		return (Package) ((IStructuredSelection) getContext().getSelection())
				.getFirstElement();
	}
}
